Wang Haihua
🚅 🚋😜 🚑 🚔
如果李梅心情不好,她会跑步,或者大吃特吃冰淇淋,要么打个盹儿来调整。
根据以往数据,如果她睡了一觉调整心情,第二天她有 60% 的可能去跑步,20% 的可能继续待在床上,还有 20% 的可能吃一大份冰淇淋。
如果她跑步散心,第二天她有 60% 的可能接着跑步,30% 的可能吃冰淇淋,只有 10% 的可能会去睡觉。
最后,如果她难过时纵情冰淇淋,第二天只有 10% 的可能性继续吃冰淇淋,有 70% 的可能性跑步,还有 20% 的可能性睡觉。
问题:从睡觉状态开始,2 天后李梅最后选择跑步的概率是多少?
我们一起算一下。要从睡觉状态转移到跑步状态,李梅有如下选择:第一天继续睡觉,第二天跑步$(0.2 \times0.6)$;第一天换成跑步,第二天继续跑步$(0.6\times0.6)$;第一天去吃冰淇淋,第二天换成跑步$(0.2 \times0.7)$。算下来概率是:$((0.2 \times 0.6) + (0.6 \times 0.6) + (0.2 \times 0.7)) = 0.62$。所以说,从睡觉状态开始,2天后李梅处于跑步状态的概率是 62%。
现在我们用 Python 来实现一下上面这个例子
先尝试随机生成李梅2天后的状态
#先 import 用到的库。
import numpy as np
import random as rm
# 状态空间
states = ["Sleep","Icecream","Run"]
# 可能的事件序列
transitionName = [["SS","SR","SI"],["RS","RR","RI"],["IS","IR","II"]]
# 概率矩阵(转移矩阵)
transitionMatrix = [[0.2,0.6,0.2],[0.1,0.6,0.3],[0.2,0.7,0.1]]
#要保证概率之和(行之和)是 1
if sum(transitionMatrix[0])+sum(transitionMatrix[1])+sum(transitionMatrix[2]) != 3:
print("Somewhere, something went wrong. Transition matrix, perhaps?")
else: print("All is gonna be okay! ")
#我们要用 numpy.random.choice 从可能的转移集合选出随机样本。
# 实现了可以预测状态的马尔可夫模型的函数。
def activity_forecast(days):
# 选择初始状态
activityToday = "Sleep"
print("Start state: " + activityToday)
# 应该记录选择的状态序列。这里现在只有初始状态。
activityList = [activityToday]
i = 0
# 计算 activityList 的概率
prob = 1
while i != days:
if activityToday == "Sleep":
change = np.random.choice(transitionName[0],replace=True,p=transitionMatrix[0])
if change == "SS":
prob = prob * 0.2
activityList.append("Sleep")
pass
elif change == "SR":
prob = prob * 0.6
activityToday = "Run"
activityList.append("Run")
else:
prob = prob * 0.2
activityToday = "Icecream"
activityList.append("Icecream")
elif activityToday == "Run":
change = np.random.choice(transitionName[1],replace=True,p=transitionMatrix[1])
if change == "RR":
prob = prob * 0.5
activityList.append("Run")
pass
elif change == "RS":
prob = prob * 0.2
activityToday = "Sleep"
activityList.append("Sleep")
else:
prob = prob * 0.3
activityToday = "Icecream"
activityList.append("Icecream")
elif activityToday == "Icecream":
change = np.random.choice(transitionName[2],replace=True,p=transitionMatrix[2])
if change == "II":
prob = prob * 0.1
activityList.append("Icecream")
pass
elif change == "IS":
prob = prob * 0.2
activityToday = "Sleep"
activityList.append("Sleep")
else:
prob = prob * 0.7
activityToday = "Run"
activityList.append("Run")
i += 1
print("Possible states: " + str(activityList))
print("End state after "+ str(days) + " days: " + activityToday)
print("Probability of the possible sequence of states: " + str(prob))
# 预测 2 天后的可能状态
activity_forecast(2)
All is gonna be okay! Start state: Sleep Possible states: ['Sleep', 'Run', 'Run'] End state after 2 days: Run Probability of the possible sequence of states: 0.3
从睡觉状态开始,迭代上几百次,就能得到终止于特定状态的预期概率。
改写了 activity_forecast 函数,加入循环
#先 import 用到的库。
import numpy as np
import random as rm
# 状态空间
states = ["Sleep","Icecream","Run"]
# 可能的事件序列
transitionName = [["SS","SR","SI"],["RS","RR","RI"],["IS","IR","II"]]
# 概率矩阵(转移矩阵)
transitionMatrix = [[0.2,0.6,0.2],[0.1,0.6,0.3],[0.2,0.7,0.1]]
#要保证概率之和(行之和)是 1
if sum(transitionMatrix[0])+sum(transitionMatrix[1])+sum(transitionMatrix[2]) != 3:
print("Somewhere, something went wrong. Transition matrix, perhaps?")
else: print("All is gonna be okay! ")
#我们要用 numpy.random.choice 从可能的转移集合选出随机样本。
# 改写了了可以预测状态的马尔可夫模型的函数。
def activity_forecast(days):
# 选择初始状态
activityToday = "Sleep"
activityList = [activityToday]
i = 0
prob = 1
while i != days:
if activityToday == "Sleep":
change = np.random.choice(transitionName[0],replace=True,p=transitionMatrix[0])
if change == "SS":
prob = prob * 0.2
activityList.append("Sleep")
pass
elif change == "SR":
prob = prob * 0.6
activityToday = "Run"
activityList.append("Run")
else:
prob = prob * 0.2
activityToday = "Icecream"
activityList.append("Icecream")
elif activityToday == "Run":
change = np.random.choice(transitionName[1],replace=True,p=transitionMatrix[1])
if change == "RR":
prob = prob * 0.5
activityList.append("Run")
pass
elif change == "RS":
prob = prob * 0.2
activityToday = "Sleep"
activityList.append("Sleep")
else:
prob = prob * 0.3
activityToday = "Icecream"
activityList.append("Icecream")
elif activityToday == "Icecream":
change = np.random.choice(transitionName[2],replace=True,p=transitionMatrix[2])
if change == "II":
prob = prob * 0.1
activityList.append("Icecream")
pass
elif change == "IS":
prob = prob * 0.2
activityToday = "Sleep"
activityList.append("Sleep")
else:
prob = prob * 0.7
activityToday = "Run"
activityList.append("Run")
i += 1
return activityList
# 记录每次的 activityList
list_activity = []
count = 0
# `range` 从第一个参数开始数起,一直到第二个参数(不包含)
for iterations in range(1,10000):
list_activity.append(activity_forecast(2))
# 查看记录到的所有 `activityList`
#print(list_activity)
# 遍历列表,得到所有最终状态是跑步的 activityList
for smaller_list in list_activity:
if(smaller_list[2] == "Run"):
count += 1
# 计算从睡觉状态开始到跑步状态结束的概率
percentage = (count/10000) * 100
print("The probability of starting at state:'Sleep' and ending at state:'Run'= " + str(percentage) + "%")
All is gonna be okay! The probability of starting at state:'Sleep' and ending at state:'Run'= 61.47%
参考文献